package com.serviceprovider.business.module.admin.bonus.controller;

//~--- non-JDK imports --------------------------------------------------------

import com.serviceprovider.business.module.admin.bonus.model.Bonus;
import com.serviceprovider.business.module.admin.bonus.model.BonusCalculationResult;
import com.serviceprovider.business.module.admin.bonus.model.BonusPayment;
import com.serviceprovider.business.module.admin.bonus.model.PayBonusForm;
import com.serviceprovider.business.module.admin.bonus.services.dao.interfaces.IBonusService;
import com.serviceprovider.business.module.admin.role.model.Role;
import com.serviceprovider.business.module.admin.role.services.dao.interfaces.IRoleService;
import com.serviceprovider.business.module.admin.user.services.dao.interfaces.IProfileService;
import com.serviceprovider.business.module.admin.user.services.dao.interfaces.IUserService;
import com.serviceprovider.business.module.common.Page;
import com.serviceprovider.business.module.user.model.impl.User;
import com.serviceprovider.business.utility.AppUtil;
import com.serviceprovider.business.utility.ApplicationConfigProperties;
import com.serviceprovider.business.utility.RequestConstants;
import com.serviceprovider.business.utility.SecurityContextUser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

//~--- JDK imports ------------------------------------------------------------

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class BonusController {
    @Autowired
    ApplicationConfigProperties applicationConfigProperties;
    @Autowired
    IBonusService               bonusService;
    @Autowired
    IProfileService             profileService;
    @Autowired
    IRoleService                roleService;
    @Autowired
    IUserService                userService;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");

        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    }

    public static int[] getInt(String csv) {
        String[] arr = ((csv == null) || csv.equals(""))
                       ? new String[0]
                       : csv.split(",");

        return AppUtil.toInt(arr);
    }

    public static double[] getDoubles(String csv, int defaultLen) {
        String[] arr = ((csv == null) || csv.equals(""))
                       ? new String[0]
                       : csv.split(",");

        if (arr.length == 0) {
            return new double[defaultLen];
        }

        return AppUtil.toDouble(arr);
    }

/*

    @RequestMapping(value = "/admin/bonus/bonus.htm")
       public ModelAndView enterBonus() {
           return new ModelAndView("admin/bonus/bonus");
      }

*/
    @RequestMapping(
        value  = RequestConstants.BonusRequests.CREATE_BONUS,
        method = RequestMethod.GET
    )
    public ModelAndView enterCreateBonus(HttpSession sess) {
        ModelAndView mav   = new ModelAndView(RequestConstants.BonusRequests.VIEW_CREATE_BONUS);
        Bonus        bonus = new Bonus();

        // List list = new ArrayList(bonusService.getTables().values());
        // bonus.setTableNameList(list);
        mav.addObject("bonus", bonus);
        mav.addObject("tableMap", bonusService.getTables());
        mav.addObject("tableList", bonusService.getTables().keySet());
        mav.addObject("mode", "Create");

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.CREATE_BONUS,
        method = RequestMethod.POST
    )
    public ModelAndView createBonus(HttpServletRequest req, @ModelAttribute("bonus") Bonus form) {
        double[] desiredAmounts = getDoubles(req.getParameter("desiredAmounts"), 0);
        int      detailLen      = desiredAmounts.length;
        String   flatRates      = req.getParameter("flatRates");
        String   percentRates   = req.getParameter("percentRates");
        int[]    roleIds        = getInt(req.getParameter("roleIds"));
        int[]    userIds        = getInt(req.getParameter("userIds"));

        bonusService.insertBonus(form, desiredAmounts, getDoubles(flatRates, detailLen),
                                 getDoubles(percentRates, detailLen), roleIds, userIds);

        return new ModelAndView("redirect:" + RequestConstants.BonusRequests.VIEW_BONUSES);
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.EDIT_BONUS,
        method = RequestMethod.GET
    )
    public ModelAndView enterEditBonus(HttpServletRequest req, HttpSession sess) throws Exception {
        ModelAndView mav       = new ModelAndView(RequestConstants.BonusRequests.VIEW_CREATE_BONUS);
        boolean      cloneMode = "true".equals(req.getParameter("clone"));
        Bonus        b         = bonusService.getBonusById(Integer.parseInt(req.getParameter("id")));

        if (cloneMode) {
            b.setRoles(new ArrayList<Role>());
            b.setUsers(new ArrayList<User>());
            b.setName("Copy of " + b.getName());
            req.setAttribute("mode", "Clone");
        } else {
            req.setAttribute("mode", "Update");
        }

        mav.addObject(b);
        mav.addObject("tableMap", bonusService.getTables());
        mav.addObject("tableList", bonusService.getTables().keySet());

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.EDIT_BONUS,
        method = RequestMethod.POST
    )
    public ModelAndView editBonus(HttpServletRequest req, @ModelAttribute("bonus") Bonus form, BindingResult result) {
        double[] desiredAmounts = getDoubles(req.getParameter("desiredAmounts"), 0);
        int      detailLen      = desiredAmounts.length;
        String   flatRates      = req.getParameter("flatRates");
        String   percentRates   = req.getParameter("percentRates");
        int[]    roleIds        = getInt(req.getParameter("roleIds"));
        int[]    userIds        = getInt(req.getParameter("userIds"));

        bonusService.updateBonus(form, desiredAmounts, getDoubles(flatRates, detailLen),
                                 getDoubles(percentRates, detailLen), roleIds, userIds);

        return new ModelAndView("redirect:" + RequestConstants.BonusRequests.VIEW_BONUSES);
    }

    @RequestMapping(value = RequestConstants.BonusRequests.VIEW_BONUSES)
    public ModelAndView viewBonuses(HttpServletRequest request) {
        ModelAndView mav        = new ModelAndView(RequestConstants.BonusRequests.VIEW_VIEW_BONUSES);
        int          recordSize = applicationConfigProperties.getRecordSize("view_bonuses.records.size");
        int          pageNo     = 1;

        try {
            pageNo = Integer.parseInt(request.getParameter("pageNo"));
        } catch (NumberFormatException ignored) {}

        String sortOrder = ((request.getParameter("sortOrder") == null)
                            || (request.getParameter("sortOrder").length() == 0))
                           ? "asc"
                           : request.getParameter("sortOrder");
        String sortColumn = ((request.getParameter("sortColumn") == null)
                             || (request.getParameter("sortColumn").length() == 0))
                            ? "id"
                            : request.getParameter("sortColumn");

        mav.addObject("bonusList", bonusService.findAll(pageNo, recordSize, sortColumn, sortOrder));

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.SELECT_ROLES,
        method = RequestMethod.GET
    )
    public ModelAndView searchUsers(HttpServletRequest req) {
        ModelAndView mav = new ModelAndView(RequestConstants.BonusRequests.VIEW_SELECT_ROLES);

        mav.addObject("roleList", roleService.findAll());

        int roleId = -1;

        try {
            roleId = Integer.parseInt(req.getParameter("roleFilter"));
        } catch (RuntimeException ignored) {}

        Page<User> listUsers;

        if (roleId != -1) {
            Role role = new Role();

            role.setId(roleId);
            listUsers = userService.findByRole(role);
        } else {
            listUsers = userService.findAll();
        }

        mav.addObject("listUsers", listUsers);

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.DELETE_BONUSES,
        method = RequestMethod.POST
    )
    public ModelAndView deleteRoles(HttpServletRequest req) {
        ModelAndView mav = new ModelAndView("redirect:" + RequestConstants.BonusRequests.VIEW_BONUSES);

        bonusService.deleteBonusesById(AppUtil.toInt(req.getParameterValues("ids")));

        return mav;
    }

    @RequestMapping(
        value  = "/admin/bonus/bonus_report.htm",
        method = RequestMethod.GET
    )
    public ModelAndView enterBonusReport(HttpSession sess) {
        ModelAndView mav  = new ModelAndView("admin/bonus/bonus_report");
        User         user = userService.getUserConnected();

        if (SecurityContextUser.isAdmin()) {
            mav.addObject("bonusList", bonusService.findAll());
        } else {
            mav.addObject("bonusList", bonusService.findBonusesByUser(user.getId()));
        }

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.BONUS_REPORT,
        method = RequestMethod.POST
    )
    public ModelAndView bonusReport(HttpServletRequest req, HttpSession sess) {
        ModelAndView mav        = new ModelAndView(RequestConstants.BonusRequests.VIEW_BONUS_REPORT);
        User         user       = userService.getUserConnected();
        String       selectedId = "" + req.getParameter("bonusId");
        String       sUserId    = req.getParameter("userId");
        List<User>   userList   = null;
        List<Bonus>  bonusList;

        if (SecurityContextUser.isAdmin()) {
            bonusList = bonusService.findAll();
            userList  = bonusService.getUsersByBonusId(new Integer(selectedId));
            mav.addObject("canPay", true);
        } else {
            bonusList = bonusService.findBonusesByUser(user.getId());
            sUserId   = user.getId() + "";
        }

        mav.addObject("bonusList", bonusList);
        mav.addObject("userList", userList);

        if ((sUserId == null) || (sUserId.length() == 0)) {
            return mav;
        }

        Integer userId = new Integer(sUserId);

        for (Bonus b : bonusList) {
            if (String.valueOf(b.getId()).equals(selectedId)) {
                BonusCalculationResult bonusResult = bonusService.computeBonus(b, userId);

                mav.addObject("bonusResult", bonusResult);
                mav.addObject("bonus", b);
                mav.addObject("reportOwner", userService.getById(userId));
            }
        }

        return mav;
    }

    @RequestMapping(value = RequestConstants.BonusRequests.BONUS_PAYMENT)
    public ModelAndView viewBonusPayment(HttpServletRequest req, HttpSession sess) throws Exception {
        ModelAndView           mav         = new ModelAndView(RequestConstants.BonusRequests.VIEW_BONUS_PAYMENT);
        String                 userEmail   = sess.getAttribute("loginUserEmail").toString();
        User                   user        = userService.getByEmail(userEmail);
        int                    paymentId   = Integer.parseInt(req.getParameter("id"));
        BonusPayment           payment     = bonusService.getBonusPayment(paymentId);
        int                    bonusId     = payment.getBonusId();
        Bonus                  b           = bonusService.getBonusById(bonusId);
        BonusCalculationResult bonusResult = bonusService.computeBonus(b, user.getId());

        mav.addObject("bonusResult", bonusResult);
        mav.addObject("bonus", b);
        mav.addObject("payment", payment);

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.PAY_BONUS,
        method = RequestMethod.GET
    )
    public ModelAndView enterPay(HttpServletRequest req, HttpSession sess) throws Exception {
        ModelAndView           mav          = new ModelAndView(RequestConstants.BonusRequests.VIEW_PAY_BONUS);
        int                    bonusId      = Integer.parseInt(req.getParameter("bonusId"));
        int                    userId       = Integer.parseInt(req.getParameter("userId"));
        Bonus                  b            = bonusService.getBonusById(bonusId);
        User                   u            = userService.getById(userId);
        BonusCalculationResult bonusResult  = bonusService.computeBonus(b, u.getId());
        PayBonusForm           payBonusForm = new PayBonusForm();

        payBonusForm.setBonusId(b.getId());
        payBonusForm.setUserId(u.getId());
        mav.addObject("bonusResult", bonusResult);
        mav.addObject("bonus", b);
        mav.addObject("reportOwner", u);
        mav.addObject("payBonusForm", payBonusForm);
        mav.addObject("payMode", req.getParameter("payMode"));

        return mav;
    }

    @RequestMapping(
        value  = RequestConstants.BonusRequests.PAY_BONUS,
        method = RequestMethod.POST
    )
    public ModelAndView pay(@ModelAttribute("payBonusForm") PayBonusForm form) {
        ModelAndView mav = new ModelAndView(RequestConstants.BonusRequests.VIEW_PAY_BONUS);

        // Bonus b = bonusService.getBonusById(form.getBonusId());
        // User u = userService.getById(form.getUserId());
        // if(form==null)throw new RuntimeException("form = "+form);
        // if(bonusService==null)throw new RuntimeException("bonusService = "+bonusService);
        // String s =
        // "bonusId = "+form.getBonusId()+",getUserId = "+form.getUserId()+"form.getPayAmount()="+form.getPayAmount()+"form.getPayAs()="+form.getPayAs();
        // if(true)throw new RuntimeException(s);
        String paymentDoneMsg = "";

        if (form.getPayMode().equals("pay")) {
            bonusService.pay(form.getBonusId(), form.getUserId(), form.getPayAmount(), form.getPayAs());
            paymentDoneMsg = "Payment has been made.";
        }

        if (form.getPayMode().equals("payOn") || form.getPayMode().equals("payWhen")) {
            bonusService.createPaymentSchedule(form);
            paymentDoneMsg = "Payment command has been scheduled.";
        }

        mav.addObject("paymentDoneMsg", paymentDoneMsg);

        /*
         * BonusCalculationResult bonusResult = bonusService.computeBonus(b, u.getId()); mav.addObject("bonusResult", bonusResult);
         * mav.addObject("bonus",b); mav.addObject("reportOwner",u); mav.addObject("payBonusForm", new PayBonusForm());
         * mav.addObject("payMode", req.getParameter("payMode"));
         */
        return mav;
    }
}



